var fs = require("fs"),
    url = require('url'),
    querystring = require('querystring');
var config = require('./config.js'); 

config.setAbsPath( __dirname.replace(/\\/g,'/') );
global.config = config;
require(config.path.base + 'protoExt.js');
global.base = require(config.path.base + 'base.js');
global.controller = require(config.path.base + 'controller.js');
global.mModel = require(config.path.base + 'model.js');


var wapMap = require(config.path.base + 'wapMap.js')

var formidable = config.etc.uploadTmp ? require('formidable') : null;
var lookuped = {};


function route(request ,response ) {
    console.log('%s / %s' ,request.headers.host  , request.url );
	try{
		var reqUrl  = url.parse('http://' + request.headers.host  + request.url , true)
	}catch(err){
		console.log ('Route Parse Error:' , request.url)
		response.writeHead(500 , {'Content-Type' : 'text/plain'});        
	    response.end('url is wrong');	
		return	
		}


    var reqPath =   reqUrl.pathname.substr(1)
	request.__request_time = new Date
    request.__get = reqUrl.query
    request.__post = {}
    var hostPath = reqUrl.hostname ?  (config.virtualHost[reqUrl.hostname]||reqUrl.hostname) : '';
    if (!reqPath){
		if (config.etc.hostDafault && config.etc.hostDafault[hostPath])
			reqPath = config.etc.hostDafault[hostPath] 
		else
			reqPath = config.etc.defaultAction
		}
	if (hostPath) hostPath += '/';

	var modUriSeg = reqPath.replace(/\/+/g,'/').split('/');
	/*
	url 格式 [/ 地址/...]模块文件名/方法名/[参数] 
	3 mod/fn/param
	2 mod/../param
	1 mod
	*/

	if (modUriSeg.length < 3){
		modUriSeg.splice(1,0,'index');
	}	

	var mods = modUriSeg.splice(-3);
	/*
	redirect some url to wap
	**/
	var ua = request.headers['user-agent']
	if (ua) ua = ua.toLowerCase()
	if (ua && 'm.veryside.com/' == hostPath && (ua.indexOf('iphone')>0 || ua.indexOf('android')>0 ) ){
		var wapUrl = wapMap.getUrl(mods,request)
		if (wapUrl) {
		    response.writeHead(301, {'Location' : wapUrl
							,'Cache-Control' : 'no-cache,must-revalidate,no-store'
							,'Pragma' : 'no-cache' })
			response.write(wapUrl)
		    response.end()
			return
		}
	}

	//modPath = './controller/' + hostPath + (modUriSeg.length ? modUriSeg.join('/')+'/' : '');
	modPath = __dirname + '/controller/' + hostPath + (modUriSeg.length ? modUriSeg.join('/')+'/' : '');

	delete modUriSeg ;
	
	
	var modName = mods[0] + '.js';
	var modFilePath = modPath + modName;


    if (!lookuped[modFilePath] && !fs.existsSync( modFilePath)){
			base.accessLog(404 , request  )
			//response.writeHead(404 , {'Content-Type' : 'text/plain'});        
		    //response.end('404');
		    html404(request,response);
        }else{
			lookuped[modFilePath] = true;
		    var mod = require ( modFilePath);
		    var fn = mods[1];
		    var param = mods.length == 3 ? mods[2] : null;
		    if (param) {
				try {
					param = decodeURIComponent(param);
				} catch(err) {
					console.log(err, param);
				}
			}
			//console.log(mod , fn);
		    if ('function' != typeof mod[fn] &&
		        'function' == typeof mod['__create']){
			    mod = mod.__create(modName , hostPath);
			    }
		    if ('function' == typeof mod[fn]){
				//base.accessLog(200 , request  )
			    exeAppScript(hostPath ,request , response , mod ,fn , param);	
		    }else if('function' == typeof mod['__call']){
			    exeAppScript(hostPath ,request , response , mod ,fn , param ,true);	
		    }else {
				base.accessLog(404 , request, modFilePath + ' not assign'  )
				//response.writeHead(404 , {'Content-Type' : 'text/plain'});        
			    //response.end('not assign.');	
			    html404(request,response);
		    }
            
     }
}


function exeAppScript(hostPath ,request , response , mod , fn , param, magicCall){
	
	var toExe = function(){
		request.headers.XREF = request.url + ' ['+ new Date().getTime().toString(32) +'.'+ (Math.random()*1000000|0).toString(32) +']'
	    mod.setRnR && mod.setRnR(request , response);
        //console.log(mod[fn]);
		if (false === mod.checkdIllegal(hostPath) ) {
			base.accessLog(421 , request,  'illegal request aborted'  )
			return;
		}
        
	    magicCall ?   mod.__call(fn,param) : mod[fn](param)   ;
        //mod[fn].call(mod , param);
	}
  	if ('POST' == request.method){
        if (formidable) {
            var form = new formidable.IncomingForm(),
                files = {},
                fields = {};

            form.uploadDir = config.etc.uploadTmp;
            form.on('field', function(field, value) {
                    fields[field] = value;
                })
                .on('file', function(field, file) {
                    files[field] = file;    
                })
                .on('end' ,function(){
  			        request.__post = fields;
                    request.__files = files;
		    	    toExe();
                    
                });
            form.parse(request);
        } else {
		    var data = '';

		    request.addListener('data' , function(chunk){
                    data += chunk;
                    if (data.length > 1e6) request.connection.destroy();
                })
		        .addListener('end' ,function(){
			        data = querystring.parse(data);

  			        request.__post = data;
			        toExe();
			    });
        }
	}else{
		toExe();
	}

}

function html404(request,response){
	var reqUrl  = url.parse('http://' + request.headers.host  + request.url , true);
	var url404 = config.path.views+config.virtualHost[reqUrl.hostname]+'/helper/404.html';
    fs.readFile(url404, "binary", function(err, file) {
        response.writeHead(200, {'Content-Type': 'text/html'});
        response.write(file, 'binary');
        response.end();
    });
}

exports.route = route;
